package site.lianwu.mybatis.plus.query.processor;

import site.lianwu.mybatis.plus.query.model.QueryClass;

import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

/**
 * 支持缓存的查询类处理器，缓存查询类
 * @author LianWu
 * @since 1.1.1
 */
public class CachedQueryClassProcessor extends QueryClassProcessorDecorator {

    /**
     * 查询类缓存
     */
    private final Map<String, QueryClass> queryClassCache = new ConcurrentHashMap<>(32);

    public CachedQueryClassProcessor(Collection<QueryFieldProcessor> queryFieldProcessors) {
        super(queryFieldProcessors);
    }

    public CachedQueryClassProcessor(Function<Collection<QueryFieldProcessor>, QueryClassProcessor> queryClassProcessorProvider) {
       super(queryClassProcessorProvider);
    }

    public CachedQueryClassProcessor(Collection<QueryFieldProcessor> queryFieldProcessors, Function<Collection<QueryFieldProcessor>, QueryClassProcessor> queryClassProcessorProvider) {
        super(queryFieldProcessors, queryClassProcessorProvider);
    }

    /**
     * 提取条件对象所属类的查询注解信息，尝试先从缓存中获取
     *
     * @param clz 条件对象所属类
     * @param includeInheritedFields 是否包含继承字段
     * @return 查询类 {@link QueryClass}
     */
    @Override
    public QueryClass extract(Class<?> clz, boolean includeInheritedFields) {
        String cacheKey = generateQueryClassCacheKey(clz, includeInheritedFields);
        // 不使用computeIfAbsent，避免死循环
        QueryClass queryClass = queryClassCache.get(cacheKey);
        if (queryClass == null) {
            queryClass = queryClassProcessor.extract(clz, includeInheritedFields);
            queryClassCache.putIfAbsent(cacheKey, queryClass);
        }
        return queryClass;
    }

    /**
     * 生成查询类缓存的键
     *
     * @param clz 条件对象所属类
     * @param includeInheritedFields 是否包含继承字段
     * @return 缓存键
     */
    private String generateQueryClassCacheKey(Class<?> clz, boolean includeInheritedFields) {
        String cacheKey = clz.getName();
        if (includeInheritedFields) {
            return cacheKey + "#includeInheritedFields";
        }
        return cacheKey;
    }

}
